import React from 'react';
import {render} from 'react-dom';
import ReactAddons from 'react-addons';
import injectTapEventPlugin from 'react-tap-event-plugin';
import axios from 'axios';
import _ from 'lodash';
import Promise from 'bluebird';
//import Router from 'core/Router.js';
import config from './config.js';
import semantic from './semantic.js';
import utils from './utils.js';
import API from './api.js';
import URL from './url.js';

import {Router, Route, Link, browserHistory, match, RouterContext} from 'react-router';
import fs from 'fs';
import path from 'path';
import createMemoryHistory from 'history/lib/createMemoryHistory';
import {renderToStaticMarkup, renderToString} from 'react-dom/server';
import {useStaticRendering} from 'mobx-react';

class Application {
    constructor() {
        this._appDom = null;
        this._config = null;
        this.observe = null;
        this.LN = '';
        this.utils = utils;
    }


    prepare({routes, lang}) {
        this.env = global == global.window ? 'browser' : 'node';
        this._routes = routes;
        this.gState = {};
        this.observers = {};
        this.storeObserver = {};
        this.eventor = {};
        this._config = config;
        this._routeParams = {};

        this.LN = '';
        this.SEM = semantic;
        this.rawAPI = API;
        this.rawURL = URL;

        return this.define()
        .prepareEventor()
        .prepareRenderConfig()
        .prepareLanguage(lang)
    }

    prepareEventor() {
        return this.initEventor();
    }

    prepareRenderConfig() {
        /*if (!global.window) {
            useStaticRendering(true);
        }*/
        return this;
    }

    prepareLanguage(lang) {

        if (~this._config.surportLanguages.indexOf(lang)) {
            if (this._config.language != lang) {

                this._config.language = lang;
            }
        }

        let mainLang = eval('(' + fs.readFileSync(path.resolve(`src/etc/lang/${this.config.mainLanguage}.lang`), 'utf8') + ')');
        //  record  let userLang = eval('(' + fs.readFileSync(path.resolve(`src/etc/lang/${lang}.lang`), 'utf8') + ')');
        let userLang = eval('(' + fs.readFileSync(path.resolve('src/etc/lang/cn.lang'), 'utf8') + ')');
        let mixLang = {...userLang, ...mainLang};

        this.LN = mixLang;

        return this;

    }

    _init({appDom, routes}) {
        this._routes = routes;
        this._appDom = appDom;
        this.gState = {};
        this.observers = {};
        this.storeObserver = {};
        this.eventor = {};
        this._config = config;
        this._routeParams = {};

        this.LN = '';
        this.SEM = semantic;
        this.rawAPI = API;
        this.rawURL = URL;

        this.define()
        .initEventor()
        .initLanguage()
        .then(() => {

            this.render();
            /*this.initConfig()
                .then(() => {


                });*/
            ////console.log(this.LN);
        });

        return this;
    }

    define() {
        Object.defineProperty(this, 'config', {
            set: function(name) {
                return false;
            },
            get: () => {
                return this._config;
            }
        });

        return this;
    }


    initEventor() {

        return this;
    }

    initConfig() {
        return axios.get('/config/frontend.json').then((res) => {
            var config;
            if (_.isString(res.data)) {
                config = eval('(' + res.data + ')');
            } else {
                config = res.data;
            }

            this._config = {...this._config, ...config};

            return config;

        });
    }

    initLanguage() {
        // var lang = global.window.location.pathname.split('/')[1];
        var lang = 'cn';
        if (~this._config.surportLanguages.indexOf(lang)) {
            if (this._config.language != lang) {

                this._config.language = lang;
            }
        } else {

            global.window.location.href = global.window.location.protocol + '//' + global.window.location.hostname + '/' + this._config.language;
            return Promise.reject();
        }


        return this.loadLanguage(this._config.language);

    }

    setRouteParams(params) {
        return this._routeParams = params;
    }

    getRouteParams(key) {
        if (key) {
            return this._routeParams[key];
        } else {
            return {...this._routeParams};

        }
    }

    url(name, params, options = {}) {
        if (options.hostPrefix) {
            if (name == 'embedUrl') {
                return this._config.urlHost + this._config.embedUrlPrefix(this._config.language) + this.rawURL[name](params);
            }
            return this._config.urlHost + this._config.urlPrefix(this._config.language) + this.rawURL[name](params);
            // option condition
        } else {
            return this._config.urlPrefix(this._config.language) + this.rawURL[name](params);
        }
    }

    api(name, params, options) {
        if (!(options && options.type)) return this._config.apiHost + this._config.apiPrefixes[0] + this.rawAPI[name](params);
    }

    /*history.listenBeforeUnload(function () {
      return 'Are you sure you want to leave this page?'
    })*/


    loadLanguage(lang) {

        return axios.get(`/assets/lang/${this._config.mainLanguage}.lang`).then((res) => {
            //console.log(res);
            var mainLangObj;

            if (_.isString(res.data)) {
                mainLangObj = eval('(' + res.data + ')');
            } else {
                mainLangObj = res.data;
            }

            this.LN = mainLangObj;


            return mainLangObj;

        }).then((mainLangObj) => {
            let mixLangObj = mainLangObj;


            if (lang && (lang != this._config.mainLanguage)) {

                return axios.get(`/assets/lang/${lang}.lang`).then((res) => {
                    //console.log(res);


                    if (_.isString(res.data)) {
                        mixLangObj = {...mainLangObj, ...eval('(' + res.data + ')')};
                    } else {
                        mixLangObj = {...mainLangObj, ...res.data};
                    }

                    this.LN = mixLangObj;
                    // this.LN = JSON.parse(res.data);
                    // this.LN = res.data;
                    // browserHistory.push(global.window.location.href);
                    //console.log(this.LN);
                    return res;
                });

            } else {

                return mixLangObj;
            }

        });


    }

    listen(name, func) {

        if (this.observers[name] && !(~this.observers[name].indexOf(func))) {
            this.observers[name].push(func);
        } else {
            this.observers[name] = [func];
        }
    }

    unlisten(name, func) {
        var index = this.observers[name].indexOf(func);
        if (this.observers[name] && (~index)) {
            this.observers[name].slice(index, 1);
        }
    }

    fire(name, ...rest) {
        if (this.storeObserver[name]) {
            this.storeObserver[name].forEach(fun => fun(...rest));
        } else {
            throw Error(name + ': this event is not exsited');
        }
    }


    setConfig(conf) {
        this._config = _.extend(this._config, conf);
        if (conf.language) {
            this.loadLanguage(this._config.language);
        }

        return this;
    }

    renderString(url) {
        if (!global.callTouchTap) {
            global.callTouchTap = true;
            injectTapEventPlugin()
        }

        //return renderToString(<Component/>);

        return new Promise((resolve, reject) => {
            let history = createMemoryHistory();
            let location = history.createLocation(url);

            match({routes: this._routes, location: location}, (err, redirect, props) => {
                // `RouterContext` is what the `Router` renders. `Router` keeps these
                // `props` in its state as it listens to `browserHistory`. But on the
                // server our app is stateless, so we need to use `match` to
                // get these props before rendering.
                const appHtml = renderToString(<RouterContext {...props}/>);
                // dump the HTML into a template, lots of ways to do this, but none are
                // really influenced by React Router, so we're just using a little
                // function, `renderPage`
                resolve(appHtml);
            });
        });


    }


    //first render
    render() {

        injectTapEventPlugin();
        var routes = this._routes;
        render(<Router history={browserHistory} routes={routes}/>, this._appDom);

        return this;
    }


}

export default Application;